Skip to content

Latest commit

 

History

History
56 lines (48 loc) · 1.73 KB

4.12.2 - 子协程+通道.md

File metadata and controls

56 lines (48 loc) · 1.73 KB

子协程+通道

除了只用底层内置的setDefer机制实现并发请求之外,还可以使用子协程+通道实现并发。

使用实例

$serv = new \swoole_http_server("127.0.0.1", 9503, SWOOLE_BASE);

$serv->on('request', function ($req, $resp) {
	$chan = new chan(2);
	go(function () use ($chan) {
		$cli = new Swoole\Coroutine\Http\Client('www.qq.com', 80);
			$cli->set(['timeout' => 10]);
			$cli->setHeaders([
			'Host' => "www.qq.com",
			"User-Agent" => 'Chrome/49.0.2587.3',
			'Accept' => 'text/html,application/xhtml+xml,application/xml',
			'Accept-Encoding' => 'gzip',
		]);
		$ret = $cli->get('/');
		$chan->push(['www.qq.com' => $cli->body]);
	});

	go(function () use ($chan) {
		$cli = new Swoole\Coroutine\Http\Client('www.163.com', 80);
		$cli->set(['timeout' => 10]);
		$cli->setHeaders([
			'Host' => "www.163.com",
			"User-Agent" => 'Chrome/49.0.2587.3',
			'Accept' => 'text/html,application/xhtml+xml,application/xml',
			'Accept-Encoding' => 'gzip',
		]);
		$ret = $cli->get('/');
		$chan->push(['www.163.com' => $cli->body]);
	});
	
	$result = [];
	for ($i = 0; $i < 2; $i++)
	{
		$result += $chan->pop();
	}
	$resp->end(json_encode($result));
});
$serv->start();

实现原理

  • onRequest中需要并发两个http请求,可使用go函数创建2个子协程,并发地请求多个URL
  • 并创建了一个chan,使用use闭包引用语法,传递给子协程
  • 主协程循环调用chan->pop,等待子协程完成任务,yield进入挂起状态
  • 并发的两个子协程其中某个完成请求时,调用chan->push将数据推送给主协程
  • 子协程完成URL请求后退出,主协程从挂起状态中恢复,继续向下执行调用$resp->end发送响应结果